﻿#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>



//1.shmget (key_t __key, size_t __size, int __shmflg)
//创建共享内存
//共享内存已经存在，打开共享内存
//可以创建多块共享内存

// 参数1： key_t key : 共享内存在内存中的位置,key大于0整数，  后面介绍一个函数ftork() ， key就是共享内存id
// int shmSize :  创建共享内存的时候，指定共存内存大小
// 如果打开一块共享内存，填写0即可
// int flag：  类似open的flag, 
/**
 * IPC_CREAT: 创建共享内存，  IPC_CREAT| IPC_EXCL： 检测共享内存是否存在
 *                              存在函数返回-1 
 *                              不存在返回0 
 * 
 * IPC_CREAT| 0664 ： 创建贡献内存的时候，需要给共享内存一个权限 
 * 
 * 
 * 返回值： 创建/打开成功 ，得到一个整数， 对应这块内存,可以理解为文件描述符
 *   -1 ：失败 
 * 
 * 
 * 
 * 2.  m_shmAddr = shmat(m_shmID,  const void *__shmaddr, 0);
 * // 当前进程管理这块共享内存 
 * 参数:
m_shmID:通过这个参数访问共享内存，shmget()函数的返回值shmaddr
__shmaddr :指定共享内存在内核中的位置，写NULL->委托内核区指定
int __shmflg:   SHM_RDONLY  只读 
0 ： 读写
 返回值： 共享内存地址
  失败： 返回-1
 * 

3.shmdt(m_shmAddr);   进程和共享内存分离     m_shmAddr  shmat的返回值
0  成功
-1 失败


4. shmctl(m_shmID, IPC_RMID, NULL): 对共享内存操作函数
 *  m_shmID 参数1： shmget 的返回值  
 *  __cmd： 
 * shmid_ds：
 *  IPC_STAT: 获取共享内存状态
 *  IPC_SET： 设置共享内存状体
 * IPC_RMID： 标记共享内存被销毁， A，B 如果在用，C 无法销毁， A，B  分离以后才销毁   shm_nattch=0的时候


//看上面参数，如果参数1获取，参数2设置，如果cmd =IPC_RMID，第三个参数无用
struct shmid_ds *__buf： 
struct shmid_ds {  //可以获取
  struct ipc_perm shm_perm;            //共享内存权限 ，共存内存创建的时候有权限 
size_t   shm_segsz;                    //共享内存大小，
time t   shm_atime;               //最后一次关联时间 
time_t   shm_dtime;               //最后一次解关联时间 
time_t   shm_ctime;               // 最后一次改变时间 
pid_t    shm_lpid;                // 共享内存是哪个进程创建出来的
shmatt_t  shm_nattch;             // 有多少个进程和该共享内存进行了操作   3个比如  abc 进程
}

  返回值：0 成功
  -1：失败
 *
 */


// key位置 
#define SHARED_MEMORY_KEY 1234
#define SHARED_MEMORY_SIZE 1024


// 进程1 写共享内存 
int main0016666()
{
	
    int shmid;
    char *shmaddr;

    // 创建共享内存段
    if ((shmid = shmget(SHARED_MEMORY_KEY, SHARED_MEMORY_SIZE, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    // 将共享内存连接到当前进程的地址空间
    if ((shmaddr = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }
	const char*  pt="write Hello, shared memory!";

    // 写入数据到共享内存
    memcpy(shmaddr,pt,strlen(pt)+1);

    printf("Data written to shared memory: %s\n", shmaddr);

    // 分离共享内存
    if (shmdt(shmaddr) == -1) {
        perror("shmdt fail");
        exit(1);
    }



  
	return 0;
}


// 进程2 ，读取共享内存
int main0016667()
{

int shmid;
    char *shmaddr;

    // 创建共享内存段
    if ((shmid = shmget(SHARED_MEMORY_KEY, 0,0)) < 0) {
        perror("shmget");
        exit(1);
    }

    shmaddr = (char*) shmat(shmid, NULL, 0);

    // 将共享内存连接到当前进程的地址空间

    printf("Data read to shared memory: %s\n", shmaddr);

    // 分离共享内存
    if (shmdt(shmaddr) == -1) {
        perror("shmdt fail");
        exit(1);
    }

	//销毁共享内存,标记删除，可以删除多次调用
	int ret = shmctl(shmid, IPC_RMID, NULL);

	if(ret == -1){
		 perror("shmctl fail ");
         exit(1);
	}



	return 0;
}



int main(){

// 进程1 写共享内存 
 //    main0016666();


// 读
	  main0016667();

      // 可以不写key 
      // __pathname 电脑上存在的路径， 比如/home
      //  整数，取之 0-255 
   //     key_t key = (const char *__pathname, int __proj_id)

	return 0;
}
